package com.jml.二期.HsahSet004;


public class JmlHashMap<K, V> implements JmlMap<K, V> {
    // 默认初始的容量为16 2的4次方
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 相当于 2^4=16

    /**
     * 加载因子为0.75f 作用对我们数组实现扩容
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
    /**
     * 最大初始化的容量 10 7374 1824
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;

    /*
     * 设置实际的加载因子
     */
    final float loadFactor;
    /**
     * 阈值 需要的扩容的时候 设置值 实际hashMap存放的大小
     * <p>
     * 容量*加载因子0.75
     * <p>
     * 当达到该阈值情况下开始实现扩容
     */
    int threshold;
    /**
     * hashMap底层数组存放为空
     */
    transient Entry<K, V>[] tables = null;
    /**
     * 集合大小
     */
    transient int size;

    /**
     * 默认的hashMap初始容量16 ，加载因子为0.75 底层数组都是为空
     */
    public JmlHashMap() {
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
    }

    /**
     * @param initialCapacity 初始的容量
     * @param loadFactor      加载因子
     */
    public JmlHashMap(int initialCapacity, float loadFactor) {
        //   检查设置的初始容量是否合理
        if (initialCapacity < 0) {
            throw new IllegalArgumentException("Illegal initial capacity: " +
                    initialCapacity);
        }
        // 如果设置的初始容量大于MAXIMUM_CAPACITY  最大的容量限制为MAXIMUM_CAPACITY
        if (initialCapacity > MAXIMUM_CAPACITY) {
            initialCapacity = MAXIMUM_CAPACITY;
        }
        // 检查设置的加载因子设置是否合理
        if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
            throw new IllegalArgumentException("Illegal load factor: " +
                    loadFactor);
        }
        // 设置我们的加载因子和 实际hashMap存放的阈值
        this.loadFactor = loadFactor;
        threshold = initialCapacity;
        init();
    }

    /**
     * 定义的空方法能够给子类实现扩展功能
     */
    protected void init() {
    }

    @Override
    public int size() {
        return 0;
    }

    @Override
    public V put(K key, V value) {
        // 如果tables 是为空的情况 开始初始化我们的数组大小
        if (tables == null) {
            inflateTable(threshold);
        }
        //计算hash值
        int hash = hash(key);
        // 根据hash值计算 数组下标存放的位置
        int index = indexFor(hash, tables.length);
        // 判断HashCode相同且对象值相同的情况下，修改value值
        for (Entry e = tables[index]; e != null; e = e.next) {
            // tables[index] 取出相同hahsCode 但是 value值不同
            Object k;
            if (e.hash == hash && ((k = e.getKey()) == key || e.getKey().equals(key))) {
                // 获取原来的value
                Object oldtValue = e.getValue();
                // 设置最新的值
                e.setValue(value);
                return (V) oldtValue;
            }
        }
        // 否则的情况下 添加元素
        addEntry(hash, key, value, index);
        return null;
    }

    /**
     * @param hash
     * @param key
     * @param value
     * @param bucketIndex 桶索引下标
     */
    void addEntry(int hash, K key, V value, int bucketIndex) {
        createEntry(hash, key, value, bucketIndex);
    }

    private void createEntry(int hash, K key, V value, int bucketIndex) {
        // 获取原来的   Entry对象 如果获取为情况下 没有发生hash冲突
        Entry<K, V> next = tables[bucketIndex];
        // 当前最新的Entry对象
        tables[bucketIndex] = new Entry(hash, key, value, next);
    }
    // 最新hashcode碰撞的在hashCode链表前面

    /**
     * 计算我们的hash值
     *
     * @param k
     * @return
     */
    final int hash(Object k) {
        int h = 0;
        if (0 != h && k instanceof String) {
            return 0;//sun.misc.Hashing.stringHash32((String) k);
        }

        h ^= k.hashCode();

        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

    // 根据hash值计算index下表位置
    static int indexFor(int h, int length) {
        // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
        return h & (length - 1);
    }

    /**
     * 默认的数组初始化
     *
     * @param toSize
     */
    private void inflateTable(int toSize) {
        int capacity = roundUpToPowerOf2(toSize);
        // 计算初始化容量  capacity16*0.75=12 ,10亿   12
        threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
        // 数组中的容量初始化
        tables = new JmlHashMap.Entry[capacity];
    }

    private static int roundUpToPowerOf2(int number) {
        // assert number >= 0 : "number must be non-negative";
        return number >= MAXIMUM_CAPACITY
                ? MAXIMUM_CAPACITY
                : (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;
    }

    @Override
    public V get(K key) {
        return null;
    }

    class Entry<K, V> implements JmlMap.Entry<K, V> {
        // key
        private K k;
        // value
        private V v;
        // next 执行下一个Entry
        private Entry<K, V> next;

        // 存放每个Entry对象的hash值
        private int hash;

        public Entry(int hash, K key, V value, Entry<K, V> next) {
            this.hash = hash;
            this.k = key;
            this.v = value;
            this.next = next;
        }
 

        public K getKey() {
            return this.k;
        }

        public V getValue() {
            return this.v;
        }

        public V setValue(V value) {
            this.v = value;
            return this.v;
        }

        public Entry(K k, V v) {
            this.k = k;
            this.v = v;
        }
    }
}
